<script setup lang="ts">
import { Group, Mesh, Object3D, BufferGeometry, Material } from 'three'
import { mergeGeometries } from 'three/examples/jsm/utils/BufferGeometryUtils'
import { useEmitt } from '@/hooks/web/useEmitt'
import { ShallowRef } from 'vue'
import EditToolEvent from './dialog/event/EditToolEvent.vue'

const message = useMessage()

const emitt = useEmitt()

// 内容 Group
const contentGroup = inject<Group>('contentGroup')!
// 当前编辑对象
const editObject = inject<ShallowRef<Object3D | null>>('editObject')!

/**
 * 添加新组
 */
const addNewGroup = () => {
  const newGroup = new Group()
  newGroup.name = 'new group'

  contentGroup.add(newGroup)
  emitt.emit('changeStructTree')
}

/**
 * 删除当前项
 */
const deleteShow = ref(false)
const deleteCurrentItem = (onlyThis: boolean = true) => {
  const parent = editObject.value!.parent
  if (onlyThis) {
    editObject.value?.children.forEach((child) => {
      parent!.add(child)
    })
  }

  editObject!.value!.removeFromParent()
  editObject.value = null
  emitt.emit('changeStructTree')
  message.success('删除成功')
  deleteShow.value = false
}

/**
 * 复制当前项
 */
const copyCurrentItem = () => {
  const newObject = editObject.value!.clone()
  newObject.name = 'new ' + newObject.name
  contentGroup.add(newObject)
  emitt.emit('changeStructTree')
  message.success('复制成功')
}

/**
 * 添加事件
 */
const eventRef = ref()
const addEvent = () => {
  eventRef.value.open()
}

/**
 * 合并对象
 */
const mergeCurrentItem = async () => {
  await message.confirm('合并后将无法撤销，且相关事件也一起合并', '合并当前对象及其子对象')

  const geometries: BufferGeometry[] = []
  const materials: Material[] = []

  editObject.value!.traverse((child: Mesh) => {
    if (!child.isMesh) return

    const geometry = child.geometry.clone()
    geometry.applyMatrix4(child.matrixWorld)
    geometries.push(geometry)
    materials.push(child.material as Material)
  })
  const mergedGeometry = mergeGeometries(geometries, true)

  const newMesh = new Mesh(mergedGeometry, materials)
  initNewMesh(newMesh)

  const parent = editObject.value!.parent!
  parent.add(newMesh)
  parent.remove(editObject.value!)
  editObject.value = newMesh

  emitt.emit('changeStructTree')
  message.success('合并成功')
}
const initNewMesh = (mesh: Mesh) => {
  mesh.name = editObject.value!.name
  {
    const {x, y, z} = editObject.value!.position
    mesh.position.set(x, y, z)
  }
  {
    const {x, y, z} = editObject.value!.rotation
    mesh.position.set(x, y, z)
  }
  {
    const {x, y, z} = editObject.value!.scale
    mesh.position.set(x, y, z)
  }

  const eventList = mesh.userData.eventList = [] as any[]
  editObject.value!.traverse((child: Mesh) => {
    const childEventList = child.userData?.eventList || []
    eventList.push(...childEventList)
  })
}
</script>

<template>
  <div>
    <el-space wrap>
      <el-button type="primary" @click="addNewGroup">添加新组</el-button>
      <el-button v-if="editObject" type="danger" @click="deleteShow = true">删除当前项</el-button>
      <el-button v-if="editObject" type="primary" @click="copyCurrentItem">复制当前项</el-button>
      <el-button v-if="editObject" type="warning" @click="mergeCurrentItem">合并当前项</el-button>
      <el-button v-if="editObject" type="primary" @click="addEvent">添加事件</el-button>
    </el-space>

    <Dialog v-model="deleteShow" title="是否删除当前项">
      <el-button @click="deleteShow = false">取消</el-button>
      <el-button type="danger" @click="deleteCurrentItem">仅删除当前项</el-button>
      <el-button type="danger" @click="deleteCurrentItem(false)">删除当前项及所有子项</el-button>
    </Dialog>

    <EditToolEvent ref="eventRef" />
  </div>
</template>

<style scoped lang="scss"></style>
